/*
 * RadioStrength.java
 *
 * Routines to turn two SPOTs into radio signal strength meters.
 *
 * author: Ron Goldman  
 * date: June 15, 2006 
 */

package org.sunspotworld.demo;

import com.sun.spot.core.resources.Resources;
import com.sun.spot.core.resources.transducers.ILed;
import com.sun.spot.core.resources.transducers.ILightSensor;
import com.sun.spot.core.resources.transducers.ISwitch;
import com.sun.spot.core.resources.transducers.ITriColorLED;
import com.sun.spot.core.resources.transducers.LEDColor;
import com.sun.spot.edemo.EDemoBoard;
import com.sun.spot.espot.peripheral.ESpot;
import com.sun.spot.ieee_802_15_4_radio.IProprietaryRadio;
import com.sun.spot.ieee_802_15_4_radio.IRadioPolicyManager;

import com.sun.spot.multihop.io.j2me.radiogram.RadiogramConnection;
import com.sun.spot.multihop.radio.NoRouteException;

import java.io.*;
import javax.microedition.io.*;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

/**
 * Application to listen for radio broadcasts from another SPOT and to
 * display the radio signal strength.
 *<p>
 * The SPOT uses the LEDs to display its status as follows:
 *<p>
 * LED 0:
 *<ul>
 *<li> Red = missed an expected packet
 *<li> Green = received a packet
 *</ul>
 * LED 1-7:
 *<ul>
 *<li> Blue = signal strength meter for RSSI of received packets
 *<li> Red  = transmit power level (in binary) 0 (min) to 32 (max)
 *<li> Green = channel number (in binary) 11 (min) to 26 (max)
 *</ul>
 *<p>
 * The SPOT uses the switches to change/view the channel and power level:
 *<ul>
 *<li> SW0 = channel select
 *<li> SW1 = power select 
 *</ul>
 *
 * Note: if the channel is changed then the SPOT will not receive any OTA commands.
 * In that case just reboot the SPOT to switch back to the default radio channel.
 *
 * @author Ron Goldman
 */
public class RadioStrength extends MIDlet {
    private static final String VERSION = "1.0";
    private static final int INITIAL_CHANNEL_NUMBER = IProprietaryRadio.DEFAULT_CHANNEL;
    private static final short PAN_ID               = IRadioPolicyManager.DEFAULT_PAN_ID;
    private static final String BEACON_PORT      = "50";
     private static final String BEACON_PORT_HOP      = "46";
    private static final int RADIO_TEST_PACKET      = 42;
     private static final int RADIO_HOP_PACKET      = 99;
    private static final int PACKETS_PER_SECOND     = 5;
    private static final int PACKET_INTERVAL        = 1000 / PACKETS_PER_SECOND;
    private static final int BOOST_LED_THRESHOLD    = 600;
    private static final int MAX_BOOST_LED_THRESHOLD = 725;
    
    private ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[0];
    private ISwitch sw2 = EDemoBoard.getInstance().getSwitches()[1];
    private ITriColorLED leds[] = EDemoBoard.getInstance().getLEDs();

    private ILightSensor light = EDemoBoard.getInstance().getLightSensor();

   public static final byte FORWARD                   = 10;
      public static final byte LEFT                   = 13;
       public static final byte RIGHT                   = 12;
       
      public static final byte BACK                   = 11;   
    
    private int channel = INITIAL_CHANNEL_NUMBER;
    private int power = 0;                             // Start with max transmit power

    private boolean xmitDo = true;
    private boolean ledsInUse = false;
    private boolean boostLEDs = false;
    private boolean maxBoostLEDs = false;
    private boolean on = false;
    
  
 
        IRadioPolicyManager rpm = (IRadioPolicyManager) Resources.lookup(IRadioPolicyManager.class);
    
    /**
     * Pause for a specified time.
     *
     * @param time the number of milliseconds to pause
     */
    private void pause (long time) {
        try {
            Thread.currentThread().sleep(time);
        } catch (InterruptedException ex) { /* ignore */ }
    }
    
    public void setLeds(LEDColor c, boolean on){
        for(int i=0;i<leds.length;i++){
            leds[i].setColor(c);
            leds[i].setOn(on);
        }
    }
    /**
     * Initialize any needed variables.
     */
    private void initialize() { 
       setLeds(LEDColor.YELLOW,true);
        rpm.setChannelNumber(channel);
       // rpm.setPanId(PAN_ID);
        rpm.setOutputPower(power - 32);
        
        
        
    }
    

    /**
     * Main application run loop.
     */
    private void run() {
        System.out.println("Radio Signal Strength Test (version " + VERSION + ")");
        System.out.println("Packet interval = " + PACKET_INTERVAL + " msec");
        
        new Thread() {
            public void run () {
                xmitBeaconLoop();
            }
        }.start();                      // spawn a thread to transmit packets

        
    }


    

    /**
     * Loop to continually transmit packets using current power level & channel setting.
     */
    private void xmitBeaconLoop () {
        //int BEACON_NUMBER=1;
		ILed led = ESpot.getInstance().getGreenLed();
        DatagramConnection txConn = null;
        xmitDo = true;
        while (xmitDo) {
           
            try {
                txConn = (DatagramConnection)Connector.open("radiogram://broadcast:" + BEACON_PORT);
                Datagram xdg = txConn.newDatagram(txConn.getMaximumLength());
          //      long count = 0;
                boolean ledOn = false;
                while (xmitDo) {
         
                   
      //    xmitHop(); 
             on = !on;
             setLeds(LEDColor.YELLOW,on);
             
                    long nextTime = System.currentTimeMillis() + PACKET_INTERVAL;
                    //count++;
                    //if (count >= Long.MAX_VALUE) { count = 0; }
                    xdg.reset();
                    xdg.writeByte(BACK);
                    xdg.writeByte(5);
                    xdg.writeByte(RIGHT);
                    xdg.writeByte(90);
                    xdg.writeByte(FORWARD);
                    xdg.writeByte(5);
                   
                    txConn.send(xdg);
                   
             
                    long delay = (nextTime - System.currentTimeMillis()) - 2;
                    if (delay > 0) {
                        pause(delay);
                    }
                }
            } catch (IOException ex) {
                // ignore
            } finally {
                if (txConn != null) {
                    try {
                        txConn.close();
                    } catch (IOException ex) { }
                }
            }
              
        }
    }
    
   
    /**
     * Loop to continually transmit packets using current power level & channel setting.
     */
    private void xmitHop () {
        this.setLeds(LEDColor.ORANGE,true);
     //   this.pause(100);
        
        try{
        RadiogramConnection conn =
(RadiogramConnection)Connector.open("radiogram://0014.4F01.0000.0556:10");
Datagram dg = conn.newDatagram(conn.getMaximumLength());

((RadiogramConnection)conn).setMaxBroadcastHops(3);
try {
dg.writeUTF("I'm here");
conn.send(dg);
//conn.receive(dg);
} catch (NoRouteException e) {}
    



finally {
conn.close();
}
        }
        catch(Exception e){}
        
        
//        int BEACON_NUMBER=1;
//        DatagramConnection txConn = null;
//        xmitDo = true;
//           
//      //  rpm.setOutputPower(power);
//            try {
//                txConn = (DatagramConnection)Connector.open("radiogram://broadcast:" + BEACON_PORT_HOP);
//                
//                    ((RadiogramConnection)txConn).setMaxBroadcastHops(3);
//                    
//                Datagram xdg = txConn.newDatagram(txConn.getMaximumLength());
//                long count = 0;
//                boolean ledOn = false;
//             //   while (xmitDo) {         
//             
//                    long nextTime = System.currentTimeMillis() + PACKET_INTERVAL;
//                    count++;
//                    if (count >= Long.MAX_VALUE) { count = 0; }
//                    xdg.reset();
//                    xdg.writeByte(RADIO_HOP_PACKET);
//                    xdg.writeInt(BEACON_NUMBER);
//                                      
//                    txConn.send(xdg);
//                   
//             
//                    long delay = (nextTime - System.currentTimeMillis()) - 2;
//                    if (delay > 0) {
//                        pause(delay);
//                    }
//              // }
//            } catch (IOException ex) {
//                // ignore
//            } finally {
//                if (txConn != null) {
//                    try {
//                        txConn.close();
//                    } catch (IOException ex) { }
//                }
//            }
            
      //  rpm.setOutputPower(power - 32); 
        
    }
    /**
     * MIDlet call to start our application.
     */
    protected void startApp() throws MIDletStateChangeException {
        initialize();
        run();
    }

    /**
     * This will never be called by the Squawk VM.
     */
    protected void pauseApp() {
        // This will never be called by the Squawk VM
    }

    /**
     * Only called if startApp throws any exception other than MIDletStateChangeException.
     */
    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
        // Only called if startApp throws any exception other than MIDletStateChangeException
    }

}
